import axios from 'axios'
import { Toast } from 'antd-mobile'

/**
 * 全局加载状态管理
 * 用于处理并发请求时的加载提示，确保多个请求同时进行时只显示一个加载提示
 */
let loadingCount = 0

/**
 * 显示全局加载提示
 * 当有请求开始时调用，只有在第一个请求时才显示加载提示
 */
const showLoading = () => {
	loadingCount++
	if (loadingCount === 1) {
		Toast.show({ icon: 'loading', content: '加载中…', duration: 0 })
	}
}

/**
 * 隐藏全局加载提示
 * 当请求完成时调用，只有在所有请求都完成时才隐藏加载提示
 */
const hideLoading = () => {
	loadingCount = Math.max(0, loadingCount - 1)
	if (loadingCount === 0) {
		Toast.clear()
	}
}

/**
 * 创建axios实例
 * 配置基础URL和超时时间
 */
const request = axios.create({
	baseURL: '/api', // 代理到后端服务器
	timeout: 30000    // 请求超时时间30秒（发送邮件可能较慢）
})

/**
 * Token 无感刷新与失败重定向支持
 */
let isRefreshing = false
type PendingResolver = (token: string) => void
const refreshQueue: PendingResolver[] = []

const getAccessToken = () => localStorage.getItem('sessionId') || localStorage.getItem('token') || ''
const getRefreshToken = () => localStorage.getItem('refreshToken') || ''
const setTokens = (accessToken: string, refreshToken?: string) => {
	if (accessToken) {
		localStorage.setItem('sessionId', accessToken)
		localStorage.setItem('token', accessToken)
	}
	if (refreshToken) localStorage.setItem('refreshToken', refreshToken)
}

const enqueue = (cb: PendingResolver) => refreshQueue.push(cb)
const flushQueue = (token: string) => {
	while (refreshQueue.length) {
		const cb = refreshQueue.shift()
		cb && cb(token)
	}
}

// 触发刷新 Token 的请求（按你的后端接口约定调整）
const refreshTokenRequest = async (): Promise<string> => {
	const refreshToken = getRefreshToken()
	if (!refreshToken) throw new Error('NO_REFRESH_TOKEN')
	const resp = await axios.post('/api/health/user/v1/refreshToken', { refreshToken })
	const data = resp?.data || {}
	if (data.status === '0000' && data.result?.sessionId) {
		const newAccess: string = data.result.sessionId
		const newRefresh: string | undefined = data.result.refreshToken
		setTokens(newAccess, newRefresh)
		return newAccess
	}
	throw new Error('REFRESH_FAILED')
}

/**
 * 简化：将普通对象转为 x-www-form-urlencoded
 */
const toUrlEncoded = (data: Record<string, unknown>): URLSearchParams => {
	const params = new URLSearchParams()
	Object.entries(data).forEach(([key, value]) => {
		params.append(key, value == null ? '' : String(value))
	})
	return params
}

/**
 * 请求拦截器
 * 在发送请求前自动添加认证信息和处理请求数据格式
 */
request.interceptors.request.use(
	(config) => {
		// 添加认证头信息
		const headers = config.headers as Record<string, string>
		headers.ak = '0110010010000' // 应用标识
		headers.sessionId = localStorage.getItem('sessionId') || localStorage.getItem('token') || '' // 会话ID
		headers.userId = localStorage.getItem('userId') || '' // 用户ID

		// POST/PUT/PATCH 数据简化处理：
		// - 如果业务方已经显式设置了 Content-Type，则尊重它，不做改写
		// - 如果未设置，则：FormData 让浏览器接管；普通对象转 x-www-form-urlencoded
		const method = config.method?.toLowerCase()
		if (method && ['post','put','patch'].includes(method) && config.data) {
			const explicitType = ((headers['Content-Type'] || (headers as unknown as Record<string, string>)['content-type']) ?? '').toLowerCase()
			const hasExplicitType = Boolean(explicitType)
			if (!hasExplicitType) {
				if (config.data instanceof FormData) {
					delete headers['Content-Type']
				} else if (typeof config.data === 'object') {
					config.data = toUrlEncoded(config.data as Record<string, unknown>)
					headers['Content-Type'] = 'application/x-www-form-urlencoded'
				}
			}
		}
		

		// 显示加载提示
		showLoading()
		return config
	},
	(error) => {
		// 请求发送失败时隐藏加载提示
		hideLoading()
		return Promise.reject(error)
		
	}
)

/**
 * 响应拦截器
 * 处理响应数据和错误，确保加载提示正确隐藏
 */
request.interceptors.response.use(
	(response) => {
		// 请求成功时隐藏加载提示
		hideLoading()
		return response
	},
	(error) => {
		// 请求失败时隐藏加载提示
		hideLoading()
		const { response, config } = error || {}
		const originalRequest = config || {}

		if (response && response.status === 401 && !originalRequest._retry) {
			originalRequest._retry = true

			if (isRefreshing) {
				return new Promise((resolve) => {
					enqueue((newToken) => {
						(originalRequest.headers as Record<string, string>).sessionId = newToken
						(originalRequest.headers as Record<string, string>).Authorization = `Bearer ${newToken}`
						resolve(request(originalRequest))
					})
				})
			}

			isRefreshing = true
			return new Promise(async (resolve, reject) => {
				try {
					const newToken = await refreshTokenRequest()
					isRefreshing = false
					flushQueue(newToken)
					(originalRequest.headers as Record<string, string>).sessionId = newToken
					(originalRequest.headers as Record<string, string>).Authorization = `Bearer ${newToken}`
					resolve(request(originalRequest))
				} catch (e) {
					isRefreshing = false
					localStorage.removeItem('sessionId')
					localStorage.removeItem('token')
					localStorage.removeItem('refreshToken')
					const current = window.location.pathname + window.location.search
					if (!current.includes('/login')) {
						Toast.show('登录已过期，请重新登录')
						window.location.replace(`/login?redirect=${encodeURIComponent(current)}`)
					}
					reject(error)
				}
			})
		}

		return Promise.reject(error)
	}
)



export default request

